﻿using Hinacom.Scheduler.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace Hinacom.Scheduler
{
    /// <summary>
    /// 提供方法获取SchedulerJob实现类。
    /// </summary>
    public class SchedulerJobFactory
    {
        private static Dictionary<string, Type> resolved = new Dictionary<string, Type>();
        /// <summary>
        /// 根据JobType配置获取对应的SchedulerJob实现类。
        /// </summary>
        /// <param name="jobTypeName">配置的JobType名称。</param>
        /// <returns>SchedulerJob实现类。</returns>
        public static Type GetJobType(string jobTypeName)
        {
            if (!resolved.ContainsKey(jobTypeName))
            {
                // 获取JobType配置
                var jobtypeConfig = SchedulerConfiguration.Current.JobTypes.Get(jobTypeName);
                if (jobtypeConfig == null)
                    throw new JobTypeConfigurationException(jobTypeName, JobTypeConfigurationException.JobTypeConfigurationExceptionType.NotConfigured);
                // 反射指定的实现类
                string[] typeParts = jobtypeConfig.Type.Split(',');
                if (typeParts.Length != 2 || typeParts[0].Trim().Length == 0 || typeParts[1].Trim().Length == 0)
                    throw new JobTypeConfigurationException(jobTypeName, JobTypeConfigurationException.JobTypeConfigurationExceptionType.WrongTypeFormat);

                Assembly ass = Assembly.Load(typeParts[1].Trim());
                Type t = ass.GetType(typeParts[0].Trim());
                resolved.Add(jobTypeName, t);
            }
            return resolved[jobTypeName];
        }
        public static string GetConfiguredJobTypeName(Type type)
        {
            var assName = type.Assembly.GetName();
            foreach (JobTypeConfiguration jobtypeConfig in SchedulerConfiguration.Current.JobTypes)
            {
                string[] typeParts = jobtypeConfig.Type.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                    .Where(n => !String.IsNullOrWhiteSpace(n))
                    .Select(n => n.Trim()).ToArray();
                
                if (typeParts.Length == 2 && typeParts[0] == type.FullName && (typeParts[1] == assName.Name || typeParts[1] == assName.FullName))
                    return jobtypeConfig.Name;
            }
            return null;
        }
    }
    /// <summary>
    /// 当配置的JobType有误时触发此错误。
    /// </summary>
    public class JobTypeConfigurationException : Exception
    {
        public JobTypeConfigurationException(string jobTypeName, JobTypeConfigurationExceptionType type)
        {
            this.jobTypeName = jobTypeName;
            this.type = type;
        }

        private string jobTypeName;
        private JobTypeConfigurationExceptionType type;

        public override string Message
        {
            get
            {
                if (this.type == JobTypeConfigurationExceptionType.WrongTypeFormat)
                    return String.Format("The configured type for \"{0}\" cannot be recognized. It should be \"{{Full Class Name}}, {{Assembly Name}}\".", jobTypeName);
                else
                    return String.Format("The requested job type \"{0}\" is not configured.", jobTypeName);
            }
        }
        /// <summary>
        /// JobType配置错误类型。
        /// </summary>
        public enum JobTypeConfigurationExceptionType
        {
            /// <summary>
            /// 指定的JobType没有配置。
            /// </summary>
            NotConfigured = 1,
            /// <summary>
            /// 配置的SchedulerJob类格式错误。
            /// </summary>
            WrongTypeFormat = 2
        }

    }

}
